package org.example.rental.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.example.rental.domain.Car;
import org.example.rental.domain.RentalGoods;
import org.example.rental.domain.RentalOrder;
import org.example.rental.domain.ReturnCar;
import org.example.rental.service.CarService;
import org.example.rental.service.RentalGoodsService;
import org.example.rental.service.RentalOrderService;
import org.example.rental.service.ReturnCarService;
import org.example.rental.mapper.ReturnCarMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.Calendar;

/**
* @author xulongxing
* @description 针对表【return_car】的数据库操作Service实现
* @createDate 2024-01-08 19:07:51
*/
@Service
public class ReturnCarServiceImpl extends ServiceImpl<ReturnCarMapper, ReturnCar>
    implements ReturnCarService{


    @Autowired
    RentalOrderService rentalOrderService;

    @Autowired
    RentalGoodsService rentalGoodsService;

    @Autowired
    CarService carService;


    /**
     * 生成还车单
     * @param returnCar
     */
    @Transactional
    public void add(ReturnCar returnCar) {
        RentalOrder order = rentalOrderService.getById(returnCar.getOrderId());
        returnCar.setCarId(order.getCarId());
        returnCar.setCarNum(order.getCarNum());
        returnCar.setRentalTime(order.getRentalTime());
        returnCar.setReturnTime(order.getReturnTime());
        returnCar.setStatus(0);
        returnCar.setWearMoney(0.0);
        returnCar.setOrderNum(order.getOrderId());
        Integer leaseMethod = order.getLeaseMethod();
        RentalGoods goods = rentalGoodsService.getById(order.getGoodsId());

        computationalCost(returnCar,order,goods.getPrice(),leaseMethod);

        this.save(returnCar);
        //更改状态
        order.setStatus(2);
        rentalOrderService.updateById(order);


    }


    //当磨损费用和实际还车日期改变时计算需返还费用
    public Double comput(ReturnCar returnCar) {
        ReturnCar car = this.getById(returnCar.getId());
        RentalOrder order = rentalOrderService.getById(car.getOrderId());
        RentalGoods goods = rentalGoodsService.getById(order.getGoodsId());
        car.setWearMoney(returnCar.getWearMoney());
        car.setRealTime(returnCar.getRealTime());
        computationalCost(car,order,goods.getPrice(),order.getLeaseMethod());

        return car.getRefundMoney();
    }


    //审核通过
    @Transactional
    public void process(ReturnCar returnCar) {
        returnCar.setStatus(1);
        this.updateById(returnCar);

        //审核通过，修改对应订单状态为已完成状态
        RentalOrder order = rentalOrderService.getById(returnCar.getOrderId());
        order.setStatus(3);
        rentalOrderService.updateById(order);

        //修改车辆状态为闲置状态
        Car car = carService.getById(order.getCarId());
        car.setStatus(0);
        carService.updateById(car);

        //修改对应的车型租借数量
        RentalGoods goods = rentalGoodsService.getById(order.getGoodsId());
        goods.setUseSizes(goods.getUseSizes()-1);
        rentalGoodsService.updateById(goods);
    }


    /**
     * 先根据租赁方式分别计算，通过判断原定还车日期是否
     * 跟实际还车日期相同，为月租是，判断是否同月，如果相同
     * 则返还费用为押金扣除磨损费用，不同则计算出差值
     * 然后加上押金扣除磨损费用，为负数时，代表用户需要补费用
     * @param returnCar
     * @param order
     * @param price
     * @param leaseMethod
     */
    public void computationalCost(ReturnCar returnCar,RentalOrder order,Integer price,Integer leaseMethod){
        //计算可返还费用
        Instant instant = returnCar.getReturnTime().toInstant();
        Instant instant2 = returnCar.getRealTime().toInstant();
        LocalDate localDate1 = instant.atZone(ZoneId.systemDefault()).toLocalDate();
        LocalDate localDate2 = instant2.atZone(ZoneId.systemDefault()).toLocalDate();
        if (leaseMethod == 0){  //日租计费
            if (localDate1.isEqual(localDate2)){
                returnCar.setRefundMoney(order.getDeposit()-returnCar.getWearMoney());
            }else {
                long daysDiff = ChronoUnit.DAYS.between(localDate2,localDate1);
                Double nums = price * daysDiff + order.getDeposit();
                returnCar.setRefundMoney(nums-returnCar.getWearMoney());
            }
        }else {  //月租计费
            if (localDate1.getMonth() == localDate2.getMonth() && localDate1.getYear() == localDate2.getYear()) {
                returnCar.setRefundMoney(order.getDeposit()-returnCar.getWearMoney());
            } else {
                long monthsDiff = ChronoUnit.MONTHS.between(localDate2,localDate1);
                Double nums = price * (monthsDiff*30) + order.getDeposit();
                returnCar.setRefundMoney(nums-returnCar.getWearMoney());
            }
        }

    }
}




